home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectPlay / Maze / MazeServer / Main.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  48.4 KB  |  1,341 lines

  1. //----------------------------------------------------------------------------    
  2. // File: main.cpp
  3. //
  4. // Desc: This is a DirectPlay 8 client/server sample. The client comes in two flavors.  
  5. //       A console based version, and a D3D client.  The D3D client can optionally 
  6. //       be run as screen saver by simply copying mazeclient.exe to your 
  7. //       \winnt\system32\ and renaming it to mazeclient.scr.  This will make 
  8. //       it a screen saver that will be detected by the display control panel.  
  9. //
  10. // Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
  11. //-----------------------------------------------------------------------------
  12. #define STRICT
  13. #define D3D_OVERLOADS
  14. #include <windows.h>
  15. #include <d3dx.h>
  16. #include <objbase.h>
  17. #include <process.h>
  18. #include <stdio.h>
  19. #include <math.h>
  20. #include <conio.h>
  21. #include <tchar.h>
  22. #include <DXErr8.h>
  23. #include "DXUtil.h"
  24.  
  25. #include "server.h"
  26. #include "Maze.h"
  27. #include "MazeServer.h"
  28.  
  29.  
  30.  
  31.  
  32. //-----------------------------------------------------------------------------
  33. // Defines, and constants
  34. //-----------------------------------------------------------------------------
  35. #define MAX_OUTPUT_QUEUE    512
  36.  
  37.  
  38.  
  39. //-----------------------------------------------------------------------------
  40. // Global variables
  41. //-----------------------------------------------------------------------------
  42. CDPlay8Server*      g_pDPlay8Server = NULL;
  43. CMazeServer         g_MazeServer;
  44. CMaze               g_Maze;
  45. HANDLE              g_hOutputThread;
  46. HANDLE              g_hUpdateThread;
  47. volatile BOOL       g_bQuitThread;
  48. HANDLE              g_hOutputEvent;
  49. TCHAR               g_szOutputBuffer[MAX_OUTPUT_QUEUE][256];
  50. CONSOLE_SCREEN_BUFFER_INFO g_SavedConsoleInfo;
  51. ServerBufferType    g_EnumLineType[MAX_OUTPUT_QUEUE];
  52. DWORD               g_dwNextOutput      = 0;
  53. DWORD               g_dwNextFreeOutput  = 0;
  54. DWORD               g_dwQueueSize       = 0;
  55. CCriticalSection    g_OutputQueueLock;
  56. HANDLE              g_hStdOut           = NULL;
  57. DWORD               g_dwNumCmdLines     = 11;
  58. DWORD               g_dwSeperatorLine;
  59. DWORD               g_dwNumLogLines;
  60. DWORD               g_dwWindowSizeY;
  61. BOOL                g_bLocalLoopback    = FALSE;
  62. DWORD               g_dwWidth           = DEFAULT_MAZE_WIDTH;
  63. DWORD               g_dwHeight          = DEFAULT_MAZE_HEIGHT;
  64. TCHAR               g_strTimeStamp[50];
  65. FLOAT               g_fNextCIRate       = 1.0f;
  66. HANDLE              g_hLogFile          = NULL;
  67. BOOL                g_bFileLogging      = TRUE;  // Change this to turn file logging off
  68.  
  69. DWORD               g_dwNumSPThreads    = 0;
  70. DWORD               g_dwSPBufferSize    = 0xffffffff; //Init to -1
  71.  
  72.  
  73. //-----------------------------------------------------------------------------
  74. // Function-prototypes
  75. //-----------------------------------------------------------------------------
  76. HRESULT      ParseCommandLine( int argc, TCHAR* argv[] );
  77. BOOL WINAPI  CtrlHandler( DWORD type );
  78. UINT WINAPI  OutputThread( LPVOID pParam );
  79. UINT WINAPI  UpdateThread( LPVOID pParam );
  80. void         ParseInput( TCHAR* pBuffer );
  81. VOID         SetupConsole( DWORD dwWindowSizeY );
  82. VOID         RestoreOldConsoleSettings();
  83. VOID         WriteLine( DWORD nCoordY, TCHAR* strBuffer );
  84. void         ClearScreen();
  85. void         UpdateTimeStamp();
  86. void         CreateTempLogFile();
  87. VOID         SuspendPowerManagement();
  88.  
  89.  
  90.  
  91.  
  92. //-----------------------------------------------------------------------------
  93. // Name: 
  94. // Desc: 
  95. //-----------------------------------------------------------------------------
  96. void __cdecl main( int argc, TCHAR* argv[] )
  97. {
  98.     HRESULT hr;
  99.  
  100.     DXUtil_Timer( TIMER_START );
  101.     srand( (DWORD) (DXUtil_Timer( TIMER_GETABSOLUTETIME ) * UINT_MAX) );
  102.  
  103.     // Parse any command line options
  104.     if( FAILED( ParseCommandLine( argc, argv ) ) )
  105.         return;
  106.  
  107.     // Tell OS's that have power management to not 
  108.     // sleep, since this app will be using the 
  109.     // network connection and need very little user input
  110.     SuspendPowerManagement();
  111.  
  112.     // Initialize COM
  113.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  114.  
  115.     // Create an event object to flag pending output messages
  116.     g_hOutputEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  117.  
  118.     if( g_bFileLogging )
  119.         CreateTempLogFile();
  120.  
  121.     // Initalize maze and server objects
  122.     if( FAILED( hr = g_Maze.Init( g_dwWidth, g_dwHeight, DEFAULT_SEED ) ) )
  123.     {
  124.         DXTRACE_ERR( TEXT("g_Maze.Init"), hr );
  125.         goto LCleanup;
  126.     }
  127.  
  128.     // Print out the size of the maze created to the screen.
  129.     TCHAR szMazeDescript[128];
  130.  
  131.     _stprintf(szMazeDescript, TEXT("Maze size (%d,%d) Created. (width,height)"), g_dwWidth, g_dwHeight);
  132.     ConsolePrintf( SLINE_LOG, szMazeDescript );
  133.  
  134.     if( FAILED( hr = g_MazeServer.Init( FALSE, &g_Maze ) ) )
  135.     {
  136.         DXTRACE_ERR( TEXT("g_MazeServer.Init"), hr );
  137.         goto LCleanup;
  138.     }
  139.  
  140.     g_pDPlay8Server = new CDPlay8Server();
  141.     if( g_pDPlay8Server == NULL )
  142.     {
  143.         DXTRACE_ERR( TEXT("new"), E_OUTOFMEMORY );
  144.         goto LCleanup;
  145.     }
  146.     
  147.     // Connect maze server module to DP server
  148.     g_pDPlay8Server->SetServer( &g_MazeServer );
  149.     g_MazeServer.SetOutboundServer( g_pDPlay8Server );
  150.  
  151.     // Set a console control handler so we can clean 
  152.     // up gracefully if we're forcibly shut down
  153.     SetConsoleCtrlHandler( CtrlHandler, TRUE );
  154.     g_hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
  155.  
  156.     // Start up the DP server, set threads before call to host.
  157.     if( FAILED( hr = g_pDPlay8Server->Start(g_dwNumSPThreads) ) )
  158.     {
  159.         DXTRACE_ERR( TEXT("Start"), hr );
  160.         g_pDPlay8Server->Shutdown();
  161.         goto LCleanup;
  162.     }
  163.     
  164.     // Attempt to set SP Buffer.
  165.     if(g_dwSPBufferSize <= MAX_SP_BUFFER)
  166.         g_pDPlay8Server->SetSPBuffer( g_dwSPBufferSize );
  167.  
  168.     // Spin up a thread to print server output
  169.     UINT dwOutputThreadID;
  170.     g_hOutputThread = (HANDLE)_beginthreadex( NULL, 0, OutputThread, NULL, 0, &dwOutputThreadID );
  171.  
  172.     // Spin up a thread to update output
  173.     UINT dwUpdateThreadID;
  174.     g_hUpdateThread = (HANDLE)_beginthreadex( NULL, 0, UpdateThread, NULL, 0, &dwUpdateThreadID );
  175.  
  176.     ConsolePrintf( SLINE_CMD, TEXT("DirectPlay8 Server started") );
  177.     ConsolePrintf( SLINE_CMD, TEXT("Type 'HELP' for a list of commands.") );
  178.  
  179.     // Set up the console
  180.     SetConsoleMode( GetStdHandle(STD_INPUT_HANDLE), 
  181.                     ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT );
  182.  
  183.     // Loop around getting and dealing with keyboard input
  184.     TCHAR buffer[512];
  185.     while( !g_bQuitThread )
  186.     {
  187.         ConsolePrintf( SLINE_PROMPT, TEXT("Command> ") );
  188.         DWORD dwRead;
  189.         ReadConsole( GetStdHandle(STD_INPUT_HANDLE), buffer, 128, &dwRead, NULL );
  190.         if( dwRead > 2 )
  191.         {
  192.             buffer[dwRead-2]=0;
  193.             ConsolePrintf( SLINE_INPUT, buffer );
  194.             ParseInput( buffer );
  195.         }
  196.     };
  197.  
  198.     // Wait for the output thread to exit
  199.     WaitForSingleObject( g_hOutputThread, INFINITE );
  200.     WaitForSingleObject( g_hUpdateThread, INFINITE );
  201.     
  202.     // Shutdown maze and server objects
  203.     g_MazeServer.Shutdown();
  204.     g_Maze.Empty();
  205.  
  206.     // Free event object
  207.     CloseHandle( g_hOutputEvent );
  208.  
  209. LCleanup:
  210.     SAFE_DELETE( g_pDPlay8Server );
  211.  
  212.     _tprintf( TEXT("Done!\n") );
  213.  
  214.     // Uninitialize COM
  215.     CoUninitialize();
  216. }
  217.  
  218.  
  219.  
  220.  
  221. //-----------------------------------------------------------------------------
  222. // Name: 
  223. // Desc: 
  224. //-----------------------------------------------------------------------------
  225. HRESULT ParseCommandLine( int argc, TCHAR* argv[] )
  226. {
  227.     
  228.     HRESULT     hr = S_OK;
  229.     
  230.     for ( int i = 1 ; i < argc ; i++ )
  231.     {
  232.         const TCHAR* strArg  = argv[i];
  233.         if( strArg[0] == '/' || strArg[0] == '-' )
  234.         {
  235.             // User wants to set a custom Maze Size in the server.
  236.             if( _tcsnicmp( strArg + 1, TEXT("SIZE:"), 4 ) == 0 )
  237.             {
  238.                 TCHAR* strHeight = (_tcsrchr(strArg+6, ','));
  239.                 if(strHeight)
  240.                 {
  241.                     // Change the value of the ',' to NULL, then move to next val.
  242.                     strHeight[0] = '\0';
  243.                     strHeight++;
  244.  
  245.                     // Assign the argument to our global variables. 
  246.                     g_dwWidth  = _ttoi( strArg+6 );
  247.                     g_dwHeight = _ttoi( strHeight );
  248.                     
  249.                     
  250.                     // Do some simple validation on the width and height.
  251.                     if( !g_dwWidth || (g_dwWidth % LOCK_GRID_SIZE) || (g_dwWidth > SERVER_MAX_WIDTH))
  252.                     {
  253.                         printf( "Invalid Width Value!\n" );
  254.                         printf( "  Width Value must be a power of 2 from  %d to %d.\n", LOCK_GRID_SIZE, SERVER_MAX_WIDTH );
  255.                         printf( "  Format: MazeServer.exe [/size:width,height]\n\n" );
  256.                         
  257.                         hr = E_INVALIDARG;
  258.                     }
  259.                     // Simple validation on the height
  260.                     else if( !g_dwHeight || (g_dwHeight % LOCK_GRID_SIZE) || (g_dwHeight > SERVER_MAX_HEIGHT))
  261.                     {
  262.                         printf( "Invalid Height Value!\n" );
  263.                         printf( "  Height Value must be a power of 2 from  %d to %d.\n", LOCK_GRID_SIZE, SERVER_MAX_HEIGHT  );
  264.                         printf( "  Format: MazeServer.exe [/size:width,height]\n\n" );
  265.                         
  266.                         hr = E_INVALIDARG;
  267.                     }
  268.  
  269.                 }
  270.                 else
  271.                 {
  272.                     printf( "Incorrect Size Format!\n" );
  273.                     printf( "  Format: MazeServer.exe [/size:width,height]\n\n" );
  274.                     
  275.                     hr = E_INVALIDARG;
  276.                 }
  277.  
  278.             }
  279.             // User wants to enter a custom number of SP Threads in the Server
  280.             else if( _tcsnicmp( strArg + 1, TEXT("SPThreads:"), 5 ) == 0 )
  281.             {
  282.                 // Points to the number of SP threads the user wants to use.
  283.                 g_dwNumSPThreads = _ttoi( strArg + 11 ); 
  284.                 
  285.                 // Do some simple validation on our computed Value.
  286.                 if((!g_dwNumSPThreads) || (g_dwNumSPThreads < MIN_SP_THREADS) || (g_dwNumSPThreads > MAX_SP_THREADS))
  287.                 {
  288.                     printf( "Incorrect SPThreads Value!\n" );
  289.                     printf( "  Number of SPThreads must be from %d to %d.\n", MIN_SP_THREADS, MAX_SP_THREADS ); 
  290.                     printf( "  Format: MazeServer.exe [/SPThreads:num]\n\n" );
  291.                 
  292.                     hr = E_INVALIDARG;
  293.                 }
  294.             }
  295.             // User wants to enter a custom SP Buffer Size on the Server
  296.             else if( _tcsnicmp( strArg + 1, TEXT("SPBuffer:"), 5 ) == 0 )
  297.             {
  298.                 // Points to the custom SP buffer the user wants to use.
  299.                 g_dwSPBufferSize = _ttoi( strArg + 10 );
  300.                 
  301.                 // Do some simple validation on our computed Value.
  302.                 if(g_dwSPBufferSize > MAX_SP_BUFFER)
  303.                 {
  304.                     printf( "Incorrect SPBuffer Value!\n" );
  305.                     printf( "  SPBuffer must be from 0 to %d.\n", MAX_SP_BUFFER ); 
  306.                     printf( "  Format: MazeServer.exe [/SPBuffer:num]\n\n" );
  307.                 
  308.                     hr = E_INVALIDARG;
  309.                 }
  310.             }
  311.             // Flag to set the size of the client buffer pack.
  312.             else if( _tcsnicmp( strArg + 1, TEXT("ClientPackSize:"), 10 ) == 0 )
  313.             {
  314.                 DWORD packsize =  _ttoi( strArg + 16 ); 
  315.                 g_MazeServer.SetClientPackSize( packsize );
  316.                 
  317.                 // Do some simple validation on our computed Value.
  318.                 if( packsize > MAX_PACK_SIZE )
  319.                 {
  320.                     printf( "Invalid Client Buffer Pack Size! \n" );
  321.                     printf( "  Client Buffer Pack Size must be from 0 bytes to %d bytes.\n", MAX_PACK_SIZE ); 
  322.                     printf( "  Format: MazeServer.exe [/ClientPackSize:num]\n\n" );
  323.                 
  324.                     hr = E_INVALIDARG;
  325.                 }
  326.             }
  327.             // Enter a custom memory pack to add
  328.             else if( _tcsnicmp( strArg + 1, TEXT("ServerPackSize:"), 10 ) == 0 )
  329.             {
  330.                 DWORD packsize =  _ttoi( strArg + 16 ); //Points to the number of bytes the 
  331.                 g_MazeServer.SetServerPackSize( packsize );
  332.                 
  333.                 // Do some simple validation on our computed Value.
  334.                 if( packsize > MAX_PACK_SIZE )
  335.                 {
  336.                     printf( "Invalid Server Buffer Pack Size! \n" );
  337.                     printf( "  Server Buffer Pack Size must be from 0 bytes to %d bytes.\n", MAX_PACK_SIZE ); 
  338.                     printf( "  Format: MazeServer.exe [/ServerPackSize:num]\n\n" );
  339.                 
  340.                     hr = E_INVALIDARG;
  341.                 }
  342.             }
  343.             // Flag to set the size of the client buffer pack.
  344.             else if( _tcsnicmp( strArg + 1, TEXT("ClientThreadWait:"), 14 ) == 0 )
  345.             {
  346.                 DWORD threadwait =  _ttoi( strArg + 18 ); 
  347.                 g_MazeServer.SetClientThreadWait( threadwait );
  348.                 
  349.                 // Do some simple validation on our computed Value.
  350.                 if( threadwait > MAX_THREAD_WAIT )
  351.                 {
  352.                     printf( "Invalid Client Thread Wait Time! \n" );
  353.                     printf( "  Client Thread Wait Time must be from 0 bytes to %d ms.\n", MAX_THREAD_WAIT ); 
  354.                     printf( "  Format: MazeServer.exe [/ClientThreadWait:num]\n\n" );
  355.                 
  356.                     hr = E_INVALIDARG;
  357.                 }
  358.             }
  359.             // Enter a custom memory pack to add
  360.             else if( _tcsnicmp( strArg + 1, TEXT("ServerThreadWait:"), 14 ) == 0 )
  361.             {
  362.                 DWORD threadwait =  _ttoi( strArg + 18 ); //Points to the number of bytes the 
  363.                 g_MazeServer.SetServerThreadWait( threadwait );
  364.                 
  365.                 // Do some simple validation on our computed Value.
  366.                 if( threadwait > MAX_THREAD_WAIT )
  367.                 {
  368.                     printf( "Invalid Server Thread Wait Time! \n" );
  369.                     printf( "  Server Thread Wait Time must be from 0 ms to %d ms.\n", MAX_THREAD_WAIT ); 
  370.                     printf( "  Format: MazeServer.exe [/ServerThreadWait:num]\n\n" );
  371.                 
  372.                     hr = E_INVALIDARG;
  373.                 }
  374.             }
  375.             else if( _tcsicmp( strArg+1, TEXT("?") ) == 0 )
  376.             {
  377.                 printf( "MazeServer\n" );
  378.                 printf( "  Format: MazeServer.exe [/SIZE:width,height] [/SPThreads:num] [/ServerPackSize:num] [/ClientPackSize:num]\n" );
  379.                 printf( "\n" );
  380.                 printf( "  Options:\n" );
  381.                 printf( "       /SIZE:x,y : Sets the Width and Height of the maze. Power of 2 from %d to %d!\n", LOCK_GRID_SIZE, SERVER_MAX_HEIGHT );
  382.                 printf( "       /SPThreads:N : Sets SP threads to N. Range from %d to %d. \n", MIN_SP_THREADS, MAX_SP_THREADS );
  383.                 printf( "       /SPBuffer:N  : Sets SP Buffer to N. Range from 0 to %d. \n", MAX_SP_BUFFER );
  384.                 printf( "       /ClientPackSize : Custom client packet buffer. Range from 0 to %d. \n", MAX_PACK_SIZE );
  385.                 printf( "       /ServerPackSize : Custom server packet buffer. Range from 0 to %d. \n", MAX_PACK_SIZE );
  386.                 printf( "       /ClientThreadWait : Custom client thread wait time. Range from 0 to %d ms. \n", MAX_THREAD_WAIT );
  387.                 printf( "       /ServerThreadWait : Custom server thread wait time. Range from 0 to %d ms. \n", MAX_THREAD_WAIT );
  388.                 printf( "\n" );
  389.                 printf( "  Examples: \n" );
  390.                 printf( "       MazeServer /size:128,128 /SPThreads:10\n" );
  391.                 printf( "       MazeConsoleClient /SPThreads:20 \n" );
  392.                 printf( "       MazeConsoleClient /size:16,128\n \n" );
  393.  
  394.                 // They just wanted info, fail the condition so as to not start the server.
  395.                 hr = E_INVALIDARG;
  396.             }   
  397.         }
  398.     }
  399.  
  400.     return hr;
  401. }
  402.  
  403.  
  404.  
  405.  
  406. //-----------------------------------------------------------------------------
  407. // Name: 
  408. // Desc: 
  409. //-----------------------------------------------------------------------------
  410. void ConsolePrintf( ServerBufferType EnumLineType, const TCHAR* fmt, ... )
  411. {
  412.     // Format the message into a buffer
  413.     TCHAR buffer[512];
  414.     _vstprintf( buffer, fmt, (CHAR*) ((&fmt)+1) );
  415.  
  416.     // Lock the output queue
  417.     g_OutputQueueLock.Enter();
  418.  
  419.     // Find free spot
  420.     if( g_dwQueueSize != MAX_OUTPUT_QUEUE )
  421.     {
  422.         // Format message into the buffer
  423.         _vstprintf( g_szOutputBuffer[g_dwNextFreeOutput], fmt, (CHAR*)((&fmt)+1) );
  424.         g_EnumLineType[g_dwNextFreeOutput] = EnumLineType;
  425.     
  426.         // Increment output pointer and wrap around
  427.         g_dwNextFreeOutput++;
  428.         if( g_dwNextFreeOutput == MAX_OUTPUT_QUEUE )
  429.             g_dwNextFreeOutput = 0;
  430.  
  431.         // Increment message count
  432.         g_dwQueueSize++;
  433.     }
  434.  
  435.     // Unlock output queue
  436.     g_OutputQueueLock.Leave();
  437.  
  438.     // Signal event so the output thread empties the queue
  439.     SetEvent( g_hOutputEvent );
  440. }
  441.  
  442.  
  443.  
  444.  
  445. //-----------------------------------------------------------------------------
  446. // Name: 
  447. // Desc: 
  448. //-----------------------------------------------------------------------------
  449. BOOL WINAPI CtrlHandler( DWORD type )
  450. {
  451.     switch ( type )
  452.     {
  453.         case CTRL_C_EVENT:
  454.         case CTRL_BREAK_EVENT:
  455.         case CTRL_CLOSE_EVENT:
  456.         case CTRL_LOGOFF_EVENT:
  457.         case CTRL_SHUTDOWN_EVENT:
  458.             // Signal thread to quit
  459.             g_bQuitThread = TRUE;
  460.             FreeConsole();
  461.             SetEvent( g_hOutputEvent );
  462.             return TRUE;
  463.     }
  464.  
  465.     return FALSE;
  466. }
  467.  
  468.  
  469.  
  470.  
  471. //-----------------------------------------------------------------------------
  472. // Name: 
  473. // Desc: 
  474. //-----------------------------------------------------------------------------
  475. UINT WINAPI UpdateThread( LPVOID pParam )
  476. {
  477.     while( 1 )
  478.     {
  479.         if( g_bQuitThread )
  480.             break;
  481.  
  482.         FLOAT fTimeLapsed = DXUtil_Timer( TIMER_GETELAPSEDTIME );
  483.         FLOAT fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
  484.         static FLOAT s_fLastStatsDisplay = fCurTime;
  485.         static FLOAT s_fLastCIDisplay = fCurTime;
  486.  
  487.         if( g_fNextCIRate != 0.0f && fCurTime - s_fLastStatsDisplay > g_fNextCIRate * 60.0f )
  488.         {
  489.             g_MazeServer.PrintStats();
  490.             s_fLastStatsDisplay = fCurTime;
  491.         }
  492.  
  493.         if( g_fNextCIRate != 0.0f && fCurTime - s_fLastCIDisplay > g_fNextCIRate * 60.0f )
  494.         {
  495.             DWORD dwNumToDisplay = g_MazeServer.GetNumPlayers() / 60;
  496.             if( dwNumToDisplay < 1 )
  497.                 dwNumToDisplay = 1;
  498.             if( dwNumToDisplay > 20 )
  499.                 dwNumToDisplay = 20;
  500.  
  501.             for( DWORD i=0; i < dwNumToDisplay; i++ )
  502.             {
  503.                 g_MazeServer.DisplayNextConnectionInfo();           
  504.             }
  505.  
  506.             s_fLastCIDisplay = fCurTime;
  507.         }
  508.  
  509.         // Sleep for a little bit to avoid maxing the CPU
  510.         Sleep( 100 );
  511.     }
  512.  
  513.     return 0;
  514. }
  515.  
  516.  
  517.  
  518.  
  519. //-----------------------------------------------------------------------------
  520. // Name: 
  521. // Desc: 
  522. //-----------------------------------------------------------------------------
  523. UINT WINAPI OutputThread( LPVOID pParam )
  524. {
  525. #define MAX_CMD_LINES 100
  526. #define MAX_LOG_LINES 100
  527.  
  528.     DWORD i;
  529.     TCHAR szLogBuffer[MAX_LOG_LINES][256];
  530.     TCHAR szCmdBuffer[MAX_CMD_LINES][256];
  531.     DWORD dwLogBufferNext = 0;
  532.     DWORD dwCmdBufferNext = 0;
  533.     DWORD dwLastPrompt = 0;
  534.     DWORD dwCoordY;
  535.     int   dwCaretPos      = 9;
  536.  
  537.     ZeroMemory( szCmdBuffer, sizeof(TCHAR)*MAX_CMD_LINES*256 );
  538.     ZeroMemory( szLogBuffer, sizeof(TCHAR)*MAX_LOG_LINES*256 );
  539.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  540.  
  541.     GetConsoleScreenBufferInfo( g_hStdOut, &g_SavedConsoleInfo );
  542.  
  543.     g_dwWindowSizeY   = 50;
  544.     g_dwSeperatorLine = g_dwWindowSizeY - g_dwNumCmdLines - 2;
  545.     g_dwNumLogLines   = g_dwWindowSizeY - g_dwNumCmdLines - 3;
  546.         
  547.     SetupConsole( g_dwWindowSizeY );
  548.     ClearScreen();
  549.     DWORD dwNumProcess;
  550.  
  551.     while ( 1 )
  552.     {
  553.         // Wait for output to be added to the queue or the quit flag to be set
  554.         WaitForSingleObject( g_hOutputEvent, INFINITE );
  555.         if( g_bQuitThread )
  556.             break;
  557.  
  558.         dwNumProcess = 0;
  559.         UpdateTimeStamp();
  560.  
  561.         // Lock output queue
  562.         g_OutputQueueLock.Enter();
  563.  
  564.         // While there are messages to print
  565.         while ( g_dwQueueSize && dwNumProcess < 5 )
  566.         {
  567.             switch( g_EnumLineType[g_dwNextOutput] )
  568.             {
  569.                 case SLINE_LOG:
  570.                 {
  571.                     // Add g_szOutputBuffer[g_dwNextOutput] to szLogBuffer array,
  572.                     // and redisplay the array on the top half of the screen
  573.                     _stprintf( szLogBuffer[dwLogBufferNext], TEXT("%s %s"), 
  574.                                g_strTimeStamp, g_szOutputBuffer[g_dwNextOutput] );
  575.  
  576. #ifdef _DEBUG
  577.                     OutputDebugString( szLogBuffer[dwLogBufferNext] );
  578.                     OutputDebugString( TEXT("\n") );
  579. #endif
  580.                     if( g_hLogFile )
  581.                     {
  582.                         DWORD dwWritten;
  583.                         WriteFile( g_hLogFile, szLogBuffer[dwLogBufferNext], 
  584.                                    lstrlen( szLogBuffer[dwLogBufferNext] ), &dwWritten, NULL );
  585.                         TCHAR strEOL = TEXT('\r');
  586.                         WriteFile( g_hLogFile, &strEOL, 
  587.                                    sizeof(TCHAR), &dwWritten, NULL );
  588.                         strEOL = TEXT('\n');
  589.                         WriteFile( g_hLogFile, &strEOL, 
  590.                                    sizeof(TCHAR), &dwWritten, NULL );
  591.  
  592.                         static float s_fLastFlushTime = DXUtil_Timer( TIMER_GETAPPTIME );
  593.                         float fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
  594.                         if( fCurTime - s_fLastFlushTime > 5.0f )
  595.                         {
  596.                             FlushFileBuffers( g_hLogFile );
  597.                             s_fLastFlushTime = fCurTime;
  598.                         }
  599.                     }
  600.  
  601.                     dwLogBufferNext++;
  602.                     dwLogBufferNext %= g_dwNumLogLines;
  603.                     dwCoordY = 0;
  604.  
  605.                     for( i=dwLogBufferNext; i<g_dwNumLogLines; i++ )
  606.                     {
  607.                         dwCoordY++;
  608.                         WriteLine( dwCoordY, szLogBuffer[i] );
  609.                     }
  610.  
  611.                     for( i=0; i<dwLogBufferNext; i++ )
  612.                     {
  613.                         dwCoordY++;
  614.                         WriteLine( dwCoordY, szLogBuffer[i] );
  615.                     }
  616.                     break;
  617.                 }
  618.  
  619.                 case SLINE_PROMPT:
  620.                 case SLINE_CMD:
  621.                 {
  622.                     // Add g_szOutputBuffer[g_dwNextOutput] to szCmdBuffer array,
  623.                     // and redisplay the array on the top half of the screen
  624.                     _tcscpy( szCmdBuffer[dwCmdBufferNext], g_szOutputBuffer[g_dwNextOutput] );
  625.  
  626. #ifdef _DEBUG
  627.                     if( g_EnumLineType[g_dwNextOutput] != SLINE_PROMPT )
  628.                     {
  629.                         OutputDebugString( szCmdBuffer[dwCmdBufferNext] );
  630.                         OutputDebugString( TEXT("\n") );
  631.                     }
  632. #endif
  633.  
  634.                     if( g_EnumLineType[g_dwNextOutput] == SLINE_PROMPT )
  635.                     {
  636.                         dwLastPrompt = dwCmdBufferNext;
  637.                         dwCaretPos = _tcslen( szCmdBuffer[dwCmdBufferNext] );
  638.                     }
  639.  
  640.                     dwCmdBufferNext++;
  641.                     dwCmdBufferNext %= g_dwNumCmdLines;
  642.                     dwCoordY = g_dwSeperatorLine;
  643.  
  644.                     for( i=dwCmdBufferNext; i<g_dwNumCmdLines; i++ )
  645.                     {
  646.                         dwCoordY++;
  647.                         WriteLine( dwCoordY, szCmdBuffer[i] );
  648.                     }
  649.  
  650.                     for( i=0; i<dwCmdBufferNext; i++ )
  651.                     {
  652.                         dwCoordY++;
  653.                         WriteLine( dwCoordY, szCmdBuffer[i] );
  654.                     }
  655.                     break;
  656.                 }
  657.  
  658.                 case SLINE_INPUT:
  659.                 {
  660.                     // Update the last prompt line in the szCmdBuffer array with this
  661.                     // string of input, so what was typed in is displayed as it scrolls
  662.                     _tcscpy( &szCmdBuffer[dwLastPrompt][dwCaretPos], g_szOutputBuffer[g_dwNextOutput] );
  663.  
  664. #ifdef _DEBUG
  665.                     OutputDebugString( szCmdBuffer[dwLastPrompt] );
  666.                     OutputDebugString( TEXT("\n") );
  667. #endif
  668.                     break;
  669.                 }
  670.             }
  671.  
  672.             if( g_EnumLineType[g_dwNextOutput] == SLINE_PROMPT )
  673.             {                 
  674.                 // Reset the cursor position if this is a cmd prompt line
  675.                 COORD coord = { (WORD)dwCaretPos, (WORD)g_dwWindowSizeY-2 };
  676.                 SetConsoleCursorPosition( g_hStdOut, coord );
  677.             }
  678.  
  679.             g_dwNextOutput++;
  680.             if( g_dwNextOutput == MAX_OUTPUT_QUEUE )
  681.                 g_dwNextOutput = 0;
  682.  
  683.             g_dwQueueSize--;
  684.             dwNumProcess++;
  685.         }
  686.  
  687.         if( g_dwQueueSize > 0 )
  688.             SetEvent( g_hOutputEvent );
  689.  
  690.         // Unlock output queue
  691.         g_OutputQueueLock.Leave();
  692.  
  693.         if( g_hLogFile )
  694.             FlushFileBuffers( g_hLogFile );
  695.     }
  696.  
  697.     _tprintf( TEXT("Stopping...") );
  698.  
  699.     // Kill server (if we had one)
  700.     if( g_pDPlay8Server )
  701.         g_pDPlay8Server->Shutdown();
  702.  
  703.     RestoreOldConsoleSettings();
  704.  
  705.     if( g_hLogFile )
  706.         CloseHandle( g_hLogFile );
  707.  
  708.     CoUninitialize();
  709.     
  710.     return 0;
  711. }
  712.  
  713.  
  714.  
  715.  
  716. //-----------------------------------------------------------------------------
  717. // Name: 
  718. // Desc: 
  719. //-----------------------------------------------------------------------------
  720. VOID SetupConsole( DWORD dwWindowSizeY )
  721. {
  722.     static TCHAR strEmpty[255] = TEXT("                                                                                                                                                                                                                                                              ");
  723.     DWORD dwWritten;
  724.     COORD coord = { 0, 0 };
  725.     SMALL_RECT rcWindow = { 0, 0, 79, (WORD)dwWindowSizeY-1 };
  726.  
  727.     SetConsoleWindowInfo( g_hStdOut, TRUE, &rcWindow );
  728.  
  729.     COORD crdBufferSize;
  730.     crdBufferSize.X = 80;
  731.     crdBufferSize.Y = (WORD)dwWindowSizeY;
  732.     SetConsoleScreenBufferSize( g_hStdOut, crdBufferSize );
  733.  
  734.     // Write a blank string first
  735.     for( int i=rcWindow.Top; i<rcWindow.Bottom; i++ )
  736.     {
  737.         coord.Y = (WORD)i;
  738.         SetConsoleCursorPosition( g_hStdOut, coord );
  739.         WriteConsole( g_hStdOut, strEmpty, rcWindow.Right + 1, &dwWritten, NULL );
  740.     }
  741. }
  742.  
  743.  
  744.  
  745.  
  746. //-----------------------------------------------------------------------------
  747. // Name: 
  748. // Desc: 
  749. //-----------------------------------------------------------------------------
  750. VOID RestoreOldConsoleSettings()
  751. {
  752.     static TCHAR strEmpty[255] = TEXT("                                                                                                                                                                                                                                                              ");
  753.     DWORD dwWritten;
  754.     COORD coord = { 0, 0 };
  755.  
  756.     SetConsoleScreenBufferSize( g_hStdOut, g_SavedConsoleInfo.dwSize );
  757.     SetConsoleWindowInfo( g_hStdOut, TRUE, &g_SavedConsoleInfo.srWindow );
  758.  
  759.     // Write a blank string first
  760.     for( int i=g_SavedConsoleInfo.srWindow.Top; 
  761.          i<g_SavedConsoleInfo.srWindow.Bottom;
  762.          i++ )
  763.     {
  764.         coord.Y = (WORD)i;
  765.         SetConsoleCursorPosition( g_hStdOut, coord );
  766.         WriteConsole( g_hStdOut, strEmpty, g_SavedConsoleInfo.srWindow.Right + 1, &dwWritten, NULL );
  767.     }
  768. }
  769.  
  770.  
  771.  
  772.  
  773. //-----------------------------------------------------------------------------
  774. // Name: 
  775. // Desc: 
  776. //-----------------------------------------------------------------------------
  777. VOID WriteLine( DWORD nCoordY, TCHAR* strBuffer )
  778. {
  779.     // Write blanks to make all strings 80 TCHARs long so that
  780.     // the old text is erased as this one is displayed
  781.     for( DWORD dwIndex = _tcslen(strBuffer); dwIndex<80; dwIndex++ )
  782.         strBuffer[dwIndex] = ' ';
  783.     strBuffer[dwIndex] = 0;
  784.  
  785.     // Write strBuffer at (0,nCoordY)
  786.     DWORD dwWritten;
  787.     COORD coord = { 0, (WORD) nCoordY };
  788.     WriteConsoleOutputCharacter( g_hStdOut, strBuffer, 80, coord, &dwWritten ); 
  789. }
  790.  
  791.  
  792.  
  793.  
  794. //-----------------------------------------------------------------------------
  795. // Name: 
  796. // Desc: 
  797. //-----------------------------------------------------------------------------
  798. void PrintHelp()
  799. {
  800.     ConsolePrintf( SLINE_CMD, TEXT("Commands:") );
  801.     ConsolePrintf( SLINE_CMD, TEXT("    STOP, LOGLEVEL, CLIENTUPDATE") );
  802.     ConsolePrintf( SLINE_CMD, TEXT("    SERVERRELIABLE, CLIENTRELIABLE") );
  803.     ConsolePrintf( SLINE_CMD, TEXT("    SERVERTIMEOUT, CLIENTTIMEOUT, STATS") );
  804.     ConsolePrintf( SLINE_CMD, TEXT("    CONNECTIONINFO, NEXTCONNECTINFO, NEXTCONNECTINFORATE") );
  805.     ConsolePrintf( SLINE_CMD, TEXT("    CLIENTPACKSIZE, SERVERPACKSIZE") );
  806.     ConsolePrintf( SLINE_CMD, TEXT("    SPTHREADS, SPBUFFER, CLIENTTHREADWAIT, SERVERTHREADWAIT") );
  807. }
  808.  
  809.  
  810.  
  811.  
  812. //-----------------------------------------------------------------------------
  813. // Name: 
  814. // Desc: 
  815. //-----------------------------------------------------------------------------
  816. void ClearScreen()
  817. {
  818.     static TCHAR strEmpty[255] = TEXT("                                                                                                                                                                                                                                                              ");
  819.     DWORD dwWritten;
  820.     COORD coord = { 0, 0 };
  821.  
  822.     // Write a blank string first
  823.     for( DWORD i=0; i<g_dwWindowSizeY; i++ )
  824.     {
  825.         coord.Y = (WORD)i;
  826.         SetConsoleCursorPosition( g_hStdOut, coord );
  827.         WriteConsole( g_hStdOut, strEmpty, g_SavedConsoleInfo.srWindow.Right + 1, &dwWritten, NULL );
  828.     }
  829.  
  830.     // Display a seperator between the two areas of the console window
  831.     TCHAR strBuffer[200];
  832.     _tcscpy( strBuffer, TEXT("-------------------------------------------------------------------------------") );
  833.     WriteLine( g_dwSeperatorLine, strBuffer );
  834. }
  835.  
  836.  
  837.  
  838.  
  839. //-----------------------------------------------------------------------------
  840. // Name: 
  841. // Desc: 
  842. //-----------------------------------------------------------------------------
  843. void ParseInput( TCHAR* buffer )
  844. {
  845.     // Strip first token from the buffer and pull to upper case
  846.     TCHAR* token = _tcstok( buffer, TEXT(" \t") );
  847.     if( token == NULL )
  848.         return;
  849.  
  850.     _tcsupr( token );
  851.  
  852.     // See what it is and act accordingly
  853.     if( !_tcscmp( token, TEXT("STATS") ) )
  854.     {
  855.         g_MazeServer.PrintStats();
  856.     }
  857.     else if( !_tcscmp( token, TEXT("STOP") ) || 
  858.              !_tcscmp( token, TEXT("QUIT") ) || 
  859.              !_tcscmp( token, TEXT("EXIT") ) ||
  860.              !_tcscmp( token, TEXT("Q") ) )
  861.     {
  862.         g_bQuitThread = TRUE;
  863.         SetEvent( g_hOutputEvent );
  864.     }
  865.     else if( !_tcscmp( token, TEXT("SERVERRELIABLE") ) || 
  866.              !_tcscmp( token, TEXT("SR") ) )
  867.     {
  868.         token = _tcstok( NULL, TEXT(" \t") );
  869.         if( token )
  870.         {
  871.             DWORD chance = _ttol( token );
  872.             if( chance > 100 )
  873.             {
  874.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 0 and 100") );
  875.             }
  876.             else
  877.             {
  878.                 g_MazeServer.SetServerReliableRate( chance );
  879.                 ConsolePrintf( SLINE_CMD, TEXT("Server reliable packet rate set to %d%%"), chance );
  880.             }
  881.         }
  882.         else
  883.         {
  884.             ConsolePrintf( SLINE_CMD, TEXT("Server reliable packet rate is %d%%"), 
  885.                           g_MazeServer.GetServerReliableRate() );
  886.         }
  887.     }
  888.     else if( !_tcscmp( token, TEXT("CLIENTRELIABLE") ) || 
  889.               !_tcscmp( token, TEXT("CR") ) )
  890.     {
  891.         token = _tcstok( NULL, TEXT(" \t") );
  892.         if( token )
  893.         {
  894.             DWORD   chance = _ttol( token );
  895.             if( chance > 100 )
  896.             {
  897.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 0 and 100") );
  898.             }
  899.             else
  900.             {
  901.                 g_MazeServer.SetClientReliableRate( chance );
  902.                 ConsolePrintf( SLINE_CMD, TEXT("Client reliable packet rate set to %d%%"), chance );
  903.             }
  904.         }
  905.         else
  906.         {
  907.             ConsolePrintf( SLINE_CMD, TEXT("Client reliable packet rate is %d%%"), 
  908.                           g_MazeServer.GetClientReliableRate() );
  909.         }
  910.     }
  911.     else if( !_tcscmp( token, TEXT("CLIENTUPDATE") ) || !_tcscmp( token, TEXT("CU") ) )
  912.     {
  913.         token = _tcstok( NULL, TEXT(" \t") );
  914.         if( token )
  915.         {
  916.             DWORD   rate = _ttol( token );
  917.             if( rate > 1500 || rate < 50 )
  918.             {
  919.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 50 and 1500 (milliseconds)") );
  920.             }
  921.             else
  922.             {
  923.                 g_MazeServer.SetClientUpdateRate( rate );
  924.                 ConsolePrintf( SLINE_CMD, TEXT("Client update frequency set to %dms"), rate );
  925.             }
  926.         }
  927.         else
  928.         {
  929.             ConsolePrintf( SLINE_CMD, TEXT("Client update frequency is %dms"), g_MazeServer.GetClientUpdateRate() );
  930.         }
  931.     }
  932.     else if( !_tcscmp( token, TEXT("SERVERTIMEOUT") ) || !_tcscmp( token, TEXT("ST") ) )
  933.     {
  934.         token = _tcstok( NULL, TEXT(" \t") );
  935.         if( token )
  936.         {
  937.             long timeout = _ttol( token );
  938.             if( timeout > 3000 || timeout < 0 )
  939.             {
  940.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 0 and 3000 (milliseconds) (0 for none)") );
  941.             }
  942.             else
  943.             {
  944.                 g_MazeServer.SetServerTimeout( timeout );
  945.                 if( timeout == 0 )
  946.                     ConsolePrintf( SLINE_CMD, TEXT("Server timeout set to 'no timeout'") );
  947.                 else
  948.                     ConsolePrintf( SLINE_CMD, TEXT("Server timeout set to %dms"), timeout );
  949.             }
  950.         }
  951.         else
  952.         {
  953.             if( g_MazeServer.GetServerTimeout() == 0 )
  954.                 ConsolePrintf( SLINE_CMD, TEXT("Server timeout set to 'no timeout'") );
  955.             else
  956.                 ConsolePrintf( SLINE_CMD, TEXT("Server timeout is %dms"), g_MazeServer.GetServerTimeout() );
  957.         }
  958.     }
  959.     else if( !_tcscmp( token, TEXT("CLIENTTIMEOUT") ) || !_tcscmp( token, TEXT("CT") ) )
  960.     {
  961.         token = _tcstok( NULL, TEXT(" \t") );
  962.         if( token )
  963.         {
  964.             long timeout = _ttol( token );
  965.             if( timeout > 3000 || timeout < 0 )
  966.             {
  967.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 0 and 3000 (milliseconds) (0 for none)") );
  968.             }
  969.             else
  970.             {
  971.                 g_MazeServer.SetClientTimeout( timeout );
  972.                 if( timeout == 0 )
  973.                     ConsolePrintf( SLINE_CMD, TEXT("Client timeout set to 'no timeout'") );
  974.                 else
  975.                     ConsolePrintf( SLINE_CMD, TEXT("Client timeout set to %dms"), timeout );
  976.             }
  977.         }
  978.         else
  979.         {
  980.             if( g_MazeServer.GetClientTimeout() == 0 )
  981.                 ConsolePrintf( SLINE_CMD, TEXT("Client timeout set to 'no timeout'") );
  982.             else
  983.                 ConsolePrintf( SLINE_CMD, TEXT("Client timeout is %dms"), g_MazeServer.GetClientTimeout() );
  984.         }
  985.     }
  986.     else if( !_tcscmp( token, TEXT("NEXTCONNECTINFORATE") ) || !_tcscmp( token, TEXT("NCIRATE") ) )
  987.     {
  988.         token = _tcstok( NULL, TEXT(" \t") );
  989.         if( token )
  990.         {
  991.             g_fNextCIRate = (float) _ttol( token );
  992.         }
  993.  
  994.         if( g_fNextCIRate == 0.0f )
  995.             ConsolePrintf( SLINE_CMD, TEXT("NEXTCONNECTIONINFO will not be called automatically") );
  996.         else
  997.             ConsolePrintf( SLINE_CMD, TEXT("NEXTCONNECTIONINFO will be called every %0.0f mins"), g_fNextCIRate );
  998.         ConsolePrintf( SLINE_CMD, TEXT("     Sets how often NEXTCONNECTIONINFO is automatically called (0 for never)") );
  999.     }
  1000.     else if( !_tcscmp( token, TEXT("NEXTCONNECTIONINFO") ) || !_tcscmp( token, TEXT("NCI") ) )
  1001.     {
  1002.         g_MazeServer.DisplayNextConnectionInfo();
  1003.     }
  1004.     else if( !_tcscmp( token, TEXT("CONNECTIONINFO") ) || !_tcscmp( token, TEXT("CI") ) )
  1005.     {
  1006.         token = _tcstok( NULL, TEXT(" \t") );
  1007.         BOOL bTokenOK = FALSE;
  1008.         if( token )
  1009.         {
  1010.             if( _tcslen(token) == 8 )
  1011.             {
  1012.                 DWORD dwID;
  1013.                 _stscanf( token, TEXT("%x"), &dwID );
  1014.                 g_MazeServer.DisplayConnectionInfo( dwID );
  1015.                 bTokenOK = TRUE;
  1016.             }
  1017.         }
  1018.  
  1019.         if( !bTokenOK )
  1020.         {
  1021.             ConsolePrintf( SLINE_CMD, TEXT("Must enter the 8 digit client DPNID") );
  1022.         }
  1023.     }
  1024.     else if( !_tcscmp( token, TEXT("LOGLEVEL") ) )
  1025.     {
  1026.         token = _tcstok( NULL, TEXT(" \t") );
  1027.         if( token )
  1028.         {
  1029.             DWORD dwLevel = _ttol( token );
  1030.             if( dwLevel > 3 )
  1031.             {
  1032.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 0 and 3") );
  1033.             }
  1034.             else
  1035.             {
  1036.                 g_MazeServer.SetLogLevel( dwLevel );
  1037.             }
  1038.         }
  1039.  
  1040.         ConsolePrintf( SLINE_CMD, TEXT("Log level set to %d"), g_MazeServer.GetLogLevel() );
  1041.         ConsolePrintf( SLINE_CMD, TEXT("     Level 1: Connects and disconnects only") );
  1042.         ConsolePrintf( SLINE_CMD, TEXT("     Level 2: Client position every 60 seconds") );
  1043.         ConsolePrintf( SLINE_CMD, TEXT("     Level 3: Show all client position ") );
  1044.     }
  1045.     else if( !_tcscmp( token, TEXT("HELP") ) || !_tcscmp( token, TEXT("?") ) )
  1046.     {
  1047.         PrintHelp();
  1048.     }
  1049.     else if( !_tcscmp( token, TEXT("CLS") ) )
  1050.     {
  1051.         ClearScreen();
  1052.     }
  1053.     else if( !_tcscmp( token, TEXT("CLIENTPACKSIZE") ) || !_tcscmp( token, TEXT("CPS") ) )
  1054.     {
  1055.         token = _tcstok( NULL, TEXT(" \t") );
  1056.         if( token )
  1057.         {
  1058.             DWORD packsize = _ttol( token );
  1059.             if( packsize > 2048 )
  1060.             {
  1061.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 0 and 2048 (bytes) (0 for none)") );
  1062.             }
  1063.             else
  1064.             {
  1065.                 g_MazeServer.SetClientPackSize( packsize );
  1066.                 if( packsize == 0 )
  1067.                     ConsolePrintf( SLINE_CMD, TEXT("Client Packsize set to 'no data'") );
  1068.                 else
  1069.                     ConsolePrintf( SLINE_CMD, TEXT("Client Packsize set to %d bytes"), packsize );
  1070.             }
  1071.         }
  1072.         else
  1073.         {
  1074.             if( g_MazeServer.GetClientPackSize() == 0 )
  1075.                 ConsolePrintf( SLINE_CMD, TEXT("Client Packsize set to 'no data'") );
  1076.             else
  1077.                 ConsolePrintf( SLINE_CMD, TEXT("Client Packsize is %d bytes"), g_MazeServer.GetClientPackSize() );
  1078.         }
  1079.     }
  1080.     else if( !_tcscmp( token, TEXT("SERVERPACKSIZE") ) || !_tcscmp( token, TEXT("SPS") ) )
  1081.     {
  1082.         token = _tcstok( NULL, TEXT(" \t") );
  1083.         if( token )
  1084.         {
  1085.             DWORD packsize = _ttol( token );
  1086.             if( packsize > 2048 )
  1087.             {
  1088.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 0 and 2048 (bytes) (0 for none)") );
  1089.             }
  1090.             else
  1091.             {
  1092.                 g_MazeServer.SetServerPackSize( packsize );
  1093.                 if( packsize == 0 )
  1094.                     ConsolePrintf( SLINE_CMD, TEXT("Server Packsize set to 'no data'") );
  1095.                 else
  1096.                     ConsolePrintf( SLINE_CMD, TEXT("Server Packsize set to %d bytes"), packsize );
  1097.             }
  1098.         }
  1099.         else
  1100.         {
  1101.             if( g_MazeServer.GetServerPackSize() == 0 )
  1102.                 ConsolePrintf( SLINE_CMD, TEXT("Server Packsize set to 'no data'") );
  1103.             else
  1104.                 ConsolePrintf( SLINE_CMD, TEXT("Server Packsize is %d bytes"), g_MazeServer.GetServerPackSize() );
  1105.         }
  1106.     }
  1107.     else if( !_tcscmp( token, TEXT("CLIENTTHREADWAIT") ) || !_tcscmp( token, TEXT("CTW") ) )
  1108.     {
  1109.         token = _tcstok( NULL, TEXT(" \t") );
  1110.         if( token )
  1111.         {
  1112.             DWORD threadwait = _ttol( token );
  1113.             if( threadwait > 60000 )
  1114.             {
  1115.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 0 and 60000 (ms) (0 for none)") );
  1116.             }
  1117.             else
  1118.             {
  1119.                 g_MazeServer.SetClientThreadWait( threadwait );
  1120.                 if( threadwait == 0 )
  1121.                     ConsolePrintf( SLINE_CMD, TEXT("Client ThreadWait set to 'no delay'") );
  1122.                 else
  1123.                     ConsolePrintf( SLINE_CMD, TEXT("Client ThreadWait set to %d ms"), threadwait );
  1124.             }
  1125.         }
  1126.         else
  1127.         {
  1128.             if( g_MazeServer.GetClientThreadWait() == 0 )
  1129.                 ConsolePrintf( SLINE_CMD, TEXT("Client ThreadWait set to 'no delay'") );
  1130.             else
  1131.                 ConsolePrintf( SLINE_CMD, TEXT("Client ThreadWait is %d ms"), g_MazeServer.GetClientThreadWait() );
  1132.         }
  1133.     }
  1134.     else if( !_tcscmp( token, TEXT("SERVERTHREADWAIT") ) || !_tcscmp( token, TEXT("STW") ) )
  1135.     {
  1136.         token = _tcstok( NULL, TEXT(" \t") );
  1137.         if( token )
  1138.         {
  1139.             DWORD threadwait = _ttol( token );
  1140.             if( threadwait > 60000 )
  1141.             {
  1142.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 0 and 60000 (ms) (0 for none)") );
  1143.             }
  1144.             else
  1145.             {
  1146.                 g_MazeServer.SetServerThreadWait( threadwait );
  1147.                 if( threadwait == 0 )
  1148.                     ConsolePrintf( SLINE_CMD, TEXT("Server ThreadWait set to 'no delay'") );
  1149.                 else
  1150.                     ConsolePrintf( SLINE_CMD, TEXT("Server ThreadWait set to %d ms"), threadwait );
  1151.             }
  1152.         }
  1153.         else
  1154.         {
  1155.             if( g_MazeServer.GetServerThreadWait() == 0 )
  1156.                 ConsolePrintf( SLINE_CMD, TEXT("Server ThreadWait set to 'no delay'") );
  1157.             else
  1158.                 ConsolePrintf( SLINE_CMD, TEXT("Server ThreadWait is %d ms"), g_MazeServer.GetServerThreadWait() );
  1159.         }
  1160.     }
  1161.     else if( !_tcscmp( token, TEXT("SPTHREADS") ) || !_tcscmp( token, TEXT("SPT") ) )
  1162.     {
  1163.         DWORD currentthreads = g_pDPlay8Server->GetNumSPThreads();
  1164.  
  1165.         token = _tcstok( NULL, TEXT(" \t") );
  1166.         if( token )
  1167.         {
  1168.             DWORD threads = _ttol( token );
  1169.             if( (threads > MAX_SP_THREADS) || (threads <= currentthreads) )
  1170.             {
  1171.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between %d and %d"), 
  1172.                                                             currentthreads, MAX_SP_THREADS );
  1173.             }
  1174.             else
  1175.             {
  1176.                 g_pDPlay8Server->SetNumSPThreads( threads );
  1177.                 ConsolePrintf( SLINE_CMD, TEXT("SP Threads Set to %d"), 
  1178.                                                 g_pDPlay8Server->GetNumSPThreads() );
  1179.             }
  1180.         }
  1181.         else
  1182.         {
  1183.             ConsolePrintf( SLINE_CMD, TEXT("SP Threads set to %d"), currentthreads );
  1184.         }
  1185.     }
  1186.     else if( !_tcscmp( token, TEXT("SPBUFFER") ) || !_tcscmp( token, TEXT("SPB") ) )
  1187.     {
  1188.         token = _tcstok( NULL, TEXT(" \t") );
  1189.         if( token )
  1190.         {
  1191.             DWORD buffer = _ttol( token );
  1192.             if( (buffer > MAX_SP_BUFFER) )
  1193.             {
  1194.                 ConsolePrintf( SLINE_CMD, TEXT("Must enter a value between 0 and %d"), MAX_SP_BUFFER );
  1195.             }
  1196.             else
  1197.             {
  1198.                 g_pDPlay8Server->SetSPBuffer( buffer );
  1199.                 ConsolePrintf( SLINE_CMD, TEXT("SP Buffer Size Set to %d"), 
  1200.                                                 g_pDPlay8Server->GetSPBuffer() );
  1201.             }
  1202.         }
  1203.         else
  1204.         {
  1205.             ConsolePrintf( SLINE_CMD, TEXT("SP Buffer Size set to %d"), g_pDPlay8Server->GetSPBuffer() );
  1206.         }
  1207.     }
  1208.  
  1209.     else
  1210.     {
  1211.         ConsolePrintf( SLINE_CMD, TEXT("Unknown command. Type HELP for list of commands") );
  1212.     }
  1213. }
  1214.  
  1215.  
  1216.  
  1217.  
  1218. //-----------------------------------------------------------------------------
  1219. // Name: 
  1220. // Desc: 
  1221. //-----------------------------------------------------------------------------
  1222. void UpdateTimeStamp()
  1223. {
  1224.     SYSTEMTIME sysTime;
  1225.     GetLocalTime( &sysTime );
  1226.     _stprintf( g_strTimeStamp, TEXT("[%02d-%02d-%02d %02d:%02d:%02d]"),
  1227.                sysTime.wMonth, sysTime.wDay, sysTime.wYear % 100, 
  1228.                sysTime.wHour, sysTime.wMinute, sysTime.wSecond );
  1229. }
  1230.     
  1231.  
  1232.     
  1233.  
  1234. //-----------------------------------------------------------------------------
  1235. // Name: 
  1236. // Desc: 
  1237. //-----------------------------------------------------------------------------
  1238. void CreateTempLogFile()
  1239. {
  1240.     BOOL bSuccess;
  1241.     TCHAR strTempPath[MAX_PATH];
  1242.     TCHAR strTempFileName[MAX_PATH];
  1243.     TCHAR strBaseName[MAX_PATH];
  1244.     TCHAR strTime[MAX_PATH];
  1245.     DWORD dwCount;
  1246.     
  1247.     GetTempPath( MAX_PATH, strTempPath );
  1248.     lstrcat( strTempPath, TEXT("DirectPlayMaze\\") );
  1249.  
  1250.     // Create the directory if it doesn't exist
  1251.     if( GetFileAttributes( strTempPath ) == -1 )
  1252.     {
  1253.         bSuccess = CreateDirectory( strTempPath, NULL );
  1254.         if( !bSuccess )
  1255.         {
  1256.             ConsolePrintf( SLINE_LOG, TEXT("Could not create create temp directory '%s'"), strTempPath );
  1257.             goto LFail;
  1258.         }
  1259.     }
  1260.  
  1261.     ConsolePrintf( SLINE_LOG, TEXT("Logging events to temporary file") );
  1262.  
  1263.     ConsolePrintf( SLINE_LOG, TEXT("Log directory:") );
  1264.     ConsolePrintf( SLINE_LOG, strTempPath );
  1265.  
  1266.     SYSTEMTIME sysTime;
  1267.     GetLocalTime( &sysTime );
  1268.     _stprintf( strTime, TEXT("server-%04d-%02d-%02d-"),
  1269.                sysTime.wYear, sysTime.wMonth, sysTime.wDay );
  1270.  
  1271.     dwCount = 0;
  1272.  
  1273.     while(TRUE)
  1274.     {
  1275.         wsprintf( strBaseName, TEXT("%s%05d.log"), strTime, dwCount );
  1276.         lstrcpy( strTempFileName, strTempPath );
  1277.         lstrcat( strTempFileName, strBaseName );
  1278.         DWORD dwResult = GetFileAttributes( strTempFileName );
  1279.         if( dwResult == -1 )
  1280.             break;
  1281.  
  1282.         dwCount++;
  1283.     }
  1284.  
  1285.     g_hLogFile = CreateFile( strTempFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, 
  1286.                              CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
  1287.     if( g_hLogFile == INVALID_HANDLE_VALUE )
  1288.     {
  1289.         ConsolePrintf( SLINE_LOG, TEXT("Could not create create temp file '%s'"), strTempFileName );
  1290.         goto LFail;
  1291.     }
  1292.  
  1293.     ConsolePrintf( SLINE_LOG, TEXT("Log file name:") );
  1294.     ConsolePrintf( SLINE_LOG, strBaseName );
  1295.     return;
  1296.  
  1297. LFail:
  1298.     ConsolePrintf( SLINE_LOG, TEXT("File logging disabled") );
  1299.     g_bFileLogging = FALSE;
  1300. }
  1301.  
  1302.  
  1303.  
  1304.  
  1305. //-----------------------------------------------------------------------------
  1306. // Name: 
  1307. // Desc: 
  1308. //-----------------------------------------------------------------------------
  1309. VOID SuspendPowerManagement()
  1310. {
  1311.     TCHAR szPath[MAX_PATH];
  1312.     HINSTANCE hInstKernel32 = NULL;
  1313.     typedef EXECUTION_STATE (WINAPI* LPSETTHREADEXECUTIONSTATE)( EXECUTION_STATE esFlags );
  1314.     LPSETTHREADEXECUTIONSTATE pSetThreadExecutionState = NULL;
  1315.  
  1316.     GetSystemDirectory(szPath, MAX_PATH);
  1317.  
  1318.     // SetThreadExecutionState() isn't availible on some old OS's, 
  1319.     // so do a LoadLibrary to get to it.
  1320.     lstrcat(szPath, TEXT("\\kernel32.dll"));
  1321.     hInstKernel32 = LoadLibrary(szPath);
  1322.  
  1323.     if (hInstKernel32 != NULL)
  1324.     {
  1325.         pSetThreadExecutionState = (LPSETTHREADEXECUTIONSTATE)GetProcAddress(hInstKernel32, "SetThreadExecutionState");
  1326.         if( pSetThreadExecutionState != NULL )
  1327.         {
  1328.             // Tell OS's that have power management to not 
  1329.             // sleep, since this app will be using the 
  1330.             // network connection and need very little user input
  1331.             pSetThreadExecutionState( ES_SYSTEM_REQUIRED | ES_CONTINUOUS );
  1332.         }
  1333.  
  1334.         FreeLibrary(hInstKernel32);
  1335.     }
  1336. }
  1337.  
  1338.  
  1339.  
  1340.  
  1341.